package com.panopset.nls;

import static com.panopset.Util.*;
import static com.panopset.Strings.*;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.panopset.Util;
import com.panopset.gui.container.PanTextField;
import com.panopset.gui.container.Validator;

/**
 * Language names.
 *
 * @author Karl Dinwiddie
 *
 */
public final class LanguageNames {

    /**
     * Map of language names.
     */
    private Map<String, Map<String, String>> names;

    /**
     * Name path target.
     */
    private static final String NAMES_PATH_TRG = PANSOPSET_USER_DIR + PATH_SEP
            + "nlsNames";

    /**
     * Name path source.
     */
    private static final String NAMES_PATH_SRC = "/com/panopset/nls/names";

    /**
     * Base locale text field.
     */
    private PanTextField baseLocaleTF;

    /**
     *
     * @return base Locale text field.
     */
    public PanTextField getBaseLocaleTF() {
        if (baseLocaleTF == null) {
            String defaultValue = "en";
            String isoLang = Locale.getDefault().getISO3Language();
            if (isoLang != null && isoLang.length() > 1) {
                isoLang = isoLang.substring(0, 2);
                String msg = validator.validate(isoLang);
                if (isPopulated(msg)) {
                    dspmsg(msg);
                } else {
                    defaultValue = isoLang;
                }
            } else {
                dspmsg(x("Current language not found") + ", "
                        + x("using English") + " (en)");
            }
            baseLocaleTF = new PanTextField(2, x("Base"), x("Base language"),
                    defaultValue);
            baseLocaleTF.addValidator(validator);
        }
        return baseLocaleTF;
    }

    /**
     * @return base Locale from text field.
     */
    public String getBaseLocale() {
        return getBaseLocaleTF().getValue();
    }

    /**
     * Set base locale.
     *
     * @param nlsCode
     *            NLS code, such as &quot;EN&quot;.
     */
    public void setBaseLocale(final String nlsCode) {
        getBaseLocaleTF().setValue(nlsCode);
    }

    /**
     * Get name.
     * @param localName
     *            Local name.
     * @return Language name in the base locale.
     */
    public static String getName(final String localName) {
        return LanguageNames.asLanguageNames().getName(
                LanguageNames.asLanguageNames().getBaseLocale(), localName);
    }

    /**
     * Get the name of a language, in a particular language.
     *
     * @param localLocaleNm
     *            Local locale name.
     * @param localName
     *            Local name.
     * @return Name of a language in the language of localName.
     */
    public String getName(final String localLocaleNm, final String localName) {
        Map<String, String> localNames = getNames().get(localLocaleNm);
        if (localNames == null) {
            dspmsg(x("No translations found for " + localLocaleNm));
            return "";
        } else {
            String rtn = localNames.get(localName);
            if (rtn == null) {
                dspmsg(x("Language ") + localName + x(" not found for ")
                        + localLocaleNm);
                return "";
            } else {
                return rtn;
            }
        }
    }

    /**
     *
     * @return Map of locale codes to language names.
     */
    public Map<String, Map<String, String>> getNames() {
        if (names == null) {
            names = new HashMap<String, Map<String, String>>();
            for (String localeName : FlagIcons.getInstance().getSpritePackage()
                    .getResourceList()) {
                String fileName = "/" + localeName + ".properties";
                try {
                    Util.copyLibraryResource(NAMES_PATH_SRC + fileName,
                            NAMES_PATH_TRG + fileName);
                } catch (IOException ex) {
                    log(x("from") + ": " + NAMES_PATH_SRC + fileName);
                    log(x("to") + ": " + NAMES_PATH_TRG + fileName);
                    Logger.getLogger(LanguageNames.class.getName()).log(
                            Level.SEVERE, null, ex);
                }
                names.put(localeName, loadPropsFromFile(new File(NAMES_PATH_TRG
                        + "/" + fileName)));
            }
        }
        return names;
    }

    /**
     * Validator.
     */
    private final Validator validator = new Validator() {

        @Override
        public String validate(final String value) {
            if (FlagIcons.getInstance().getSpritePackage().getResourceList()
                    .contains(value)) {
                return "";
            } else {
                return x("No FlagIcon exists for language code") + " "
                        + value + " " + x("using English") + " (en)";
            }
        }

    };

    /**
     * Singleton instance.
     */
    private static LanguageNames singleton;

    /**
     *
     * @return LanguageNames singleton instance.
     */
    public static LanguageNames asLanguageNames() {
        if (singleton == null) {
            singleton = new LanguageNames();
        }
        return singleton;
    }

    /**
     * Private constructor.
     */
    private LanguageNames() {
    }

}
